/*
 * Copyright 2008 Max Kugland
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.splink.asbeangen.templates.as3;

import java.util.List;

import org.splink.asbeangen.templates.ClassTemplateHelper;
import org.splink.asbeangen.templates.IClassTemplate;

public class AS3Template implements IClassTemplate {
	public static String NEW_LINE = System.getProperty("line.separator");

	private String _dataClassPostfix;
	private String _packerClassPostfix;

	public AS3Template(String dataClassPostfix, String packerClassPostfix) {
		_dataClassPostfix = dataClassPostfix;
		_packerClassPostfix = packerClassPostfix;
	}

	public String getComment(List<String> comment) {
		String r = "/**" + NEW_LINE;
		for (int i = 0; i < comment.size(); i++) {
			r += " * " + comment.get(i) + NEW_LINE;
		}
		return r + " */" + NEW_LINE;
	}

	public String getOpenPackage(String packagename) {
		return "package " + packagename + NEW_LINE + "{" + NEW_LINE;
	}

	public String getClosePackage() {
		return "}";
	}

	public String getImport(String classpath) {
		String cp = "";
		if (classpath.indexOf(".") != -1) {
			String[] s = classpath.split("\\.");
			cp = classpath.substring(0, classpath.lastIndexOf(".") + 1)
					+ ClassTemplateHelper.firstCharToUpperCase(s[s.length - 1]);
		} else
			cp = ClassTemplateHelper.firstCharToUpperCase(classpath);

		return "	import " + cp + ";" + NEW_LINE;
	}

	public String getOpenClass(String classname) {
		return NEW_LINE + "	public class " + ClassTemplateHelper.firstCharToUpperCase(classname) + NEW_LINE + "	{"
				+ NEW_LINE;
	}

	public String getOpenClassImplements(String classname, List<String> interfazes) {
		return NEW_LINE + "	public class " + ClassTemplateHelper.firstCharToUpperCase(classname) + " implements "
				+ getInterfaces(interfazes) + NEW_LINE + "	{" + NEW_LINE;
	}

	private String getInterfaces(List<String> interfazes) {
		String r = "";
		for (String str : interfazes) {
			r += str + ", ";
		}
		r = r.substring(0, r.length() - 2);
		return r;
	}

	public String getCloseClass() {
		return "	}" + NEW_LINE;
	}

	public String getParameter(String name, String type) {
		name = ClassTemplateHelper.firstCharToLowerCase(name);

		return name + ":" + type + ", ";
	}

	public String getMemberAllocation(String name) {
		name = ClassTemplateHelper.firstCharToLowerCase(name);

		return "			_" + name + " = " + name + ";" + NEW_LINE;
	}

	public String getMember(String name, String type) {
		name = ClassTemplateHelper.firstCharToLowerCase(name);
		return "		private var _" + name + " : " + type + ";" + NEW_LINE;
	}

	public String getOpenConstructorHead(String name) {
		return NEW_LINE + "		public function " + ClassTemplateHelper.firstCharToUpperCase(name) + "(";
	}

	public String getOpenConstructorBody(String name) {
		return ")" + NEW_LINE + "		{" + NEW_LINE;
	}

	public String getCloseConstructor() {
		return "		}" + NEW_LINE + NEW_LINE;
	}

	public String getGetMethod(String name, String returntype) {
		String ar = "";
		String comment = "";
		String membername = "_"+ ClassTemplateHelper.firstCharToLowerCase(name);
		String returnStatement = "return "  + membername+ ";";
		if (returntype == "Array") {
			comment = "		/**" + NEW_LINE + "		* @return an array of " + ClassTemplateHelper.firstCharToUpperCase(name)
					+ " objects" + NEW_LINE + "		*/" + NEW_LINE;
			ar = "Array";
			returnStatement = "return "  + membername + " ? " + membername+" : new Array();";
		}
		
		return comment + "		public function get" + ClassTemplateHelper.firstCharToUpperCase(name) + ar + "() : "
				+ returntype + NEW_LINE + "		{" + NEW_LINE + "			" + returnStatement + NEW_LINE + "		}" + NEW_LINE + NEW_LINE;
	}

	public String getSetMethod(String name, String settype) {
		String ar = "";
		String comment = "";
		if (settype == "Array") {
			comment = "		/**" + NEW_LINE + "		* @param an array of " + ClassTemplateHelper.firstCharToUpperCase(name)
					+ " objects" + NEW_LINE + "		*/" + NEW_LINE;
			ar = "Array";
		}

		return comment + "		public function set" + ClassTemplateHelper.firstCharToUpperCase(name) + ar + "(value:"
				+ settype + ") : void" + NEW_LINE + "		{" + NEW_LINE + "			_"
				+ ClassTemplateHelper.firstCharToLowerCase(name) + " = value;" + NEW_LINE + "		}" + NEW_LINE + NEW_LINE;
	}

	public String getAccessMethod(String name, String accessor, String type) {
		name = ClassTemplateHelper.firstCharToLowerCase(name);
		accessor = ClassTemplateHelper.firstCharToLowerCase(accessor);

		return "		public function get" + ClassTemplateHelper.firstCharToUpperCase(name) + "By"
				+ ClassTemplateHelper.firstCharToUpperCase(accessor) + "(" + accessor + ":" + type + ") : "
				+ ClassTemplateHelper.firstCharToUpperCase(name) + NEW_LINE + "		{" + NEW_LINE + "			var d:"
				+ ClassTemplateHelper.firstCharToUpperCase(name) + ";" + NEW_LINE + "			var r:"
				+ ClassTemplateHelper.firstCharToUpperCase(name) + " = null;" + NEW_LINE + "			for (var i:int=0; i<_"
				+ name + ".length; i++)" + NEW_LINE + "			{" + NEW_LINE + "				d = _" + name + "[i];" + NEW_LINE
				+ "				if(d.get" + ClassTemplateHelper.firstCharToUpperCase(accessor) + "() == " + accessor + ")"
				+ NEW_LINE + "				{" + NEW_LINE + "					r = d;" + NEW_LINE + "					break;" + NEW_LINE + "				}"
				+ NEW_LINE + "			}" + NEW_LINE + "			return r;" + NEW_LINE + "		}" + NEW_LINE + NEW_LINE;
	}

	public String getOpenReadMethod(String returntype) {
		returntype = ClassTemplateHelper.firstCharToLowerCase(returntype);
		return "		public function read() : " + ClassTemplateHelper.firstCharToUpperCase(returntype) + NEW_LINE + "		{"
				+ NEW_LINE + "			var " + returntype + ":" + ClassTemplateHelper.firstCharToUpperCase(returntype)
				+ " = new " + ClassTemplateHelper.firstCharToUpperCase(returntype) + "();" + NEW_LINE;
	}

	public String getClosePackMethod(String returntype) {
		returntype = ClassTemplateHelper.firstCharToLowerCase(returntype);

		return NEW_LINE + "			return " + returntype + ";" + NEW_LINE + "		}" + NEW_LINE + NEW_LINE;
	}

	public String getReadAttribute(String dataTypeName, String attribute, boolean handleExeption, String type) {
		dataTypeName = ClassTemplateHelper.firstCharToLowerCase(dataTypeName);
		attribute = ClassTemplateHelper.firstCharToLowerCase(attribute);

		String intendation = "";
		if (handleExeption)
			intendation = "	";

		String caseBoolean = "";
		if (type.trim().equals("Boolean"))
			caseBoolean = " == 'true'";

		return tryStart(" 			", handleExeption) + NEW_LINE + intendation + "			" + dataTypeName + "." + "set"
				+ ClassTemplateHelper.firstCharToUpperCase(attribute) + "(_xml.@" + attribute + caseBoolean + ");"
				+ NEW_LINE + tryEnd(" 			", handleExeption, attribute);
	}

	public String getReadContent(String type) {
		type = ClassTemplateHelper.firstCharToLowerCase(type);

		return "			" + type + "." + "setContent(_xml.text());" + NEW_LINE + NEW_LINE;
	}

	public String getReadPcData(String name, String type, boolean handleExeption) {
		String n = ClassTemplateHelper.firstCharToUpperCase(name);
		type = ClassTemplateHelper.firstCharToLowerCase(type);

		String intendation = "";
		if (handleExeption)
			intendation = "	";

		return tryStart(" 			", handleExeption) + NEW_LINE + intendation + "			" + type + "." + "set" + n + "(_xml['"
				+ name + "'].text());" + NEW_LINE + NEW_LINE
				+ tryEnd(" 			", handleExeption, ClassTemplateHelper.firstCharToLowerCase(name));
	}

	public String getReadSubReader(String type, String subelement, boolean handleExeption) {
		type = ClassTemplateHelper.firstCharToLowerCase(type);
		String originalSubelement = subelement;
		subelement = ClassTemplateHelper.firstCharToLowerCase(subelement);

		String intendation = "";
		if (handleExeption)
			intendation = "	";
		String cname = ClassTemplateHelper.firstCharToUpperCase(subelement + _dataClassPostfix + _packerClassPostfix);

		return tryStart(" 			", handleExeption) + NEW_LINE + intendation + "			var " + subelement + _dataClassPostfix
				+ _packerClassPostfix + ":" + cname + " = new " + cname + "(XML(_xml['" + originalSubelement + "']));"
				+ NEW_LINE + intendation + "			" + type + "." + "set"
				+ ClassTemplateHelper.firstCharToUpperCase(subelement) + _dataClassPostfix + "(" + subelement
				+ _dataClassPostfix + _packerClassPostfix + ".read());" + NEW_LINE
				+ tryEnd(" 			", handleExeption, subelement);
	}

	public String getReadSubArReader(String type, String subelement, boolean handleExeption) {
		type = ClassTemplateHelper.firstCharToLowerCase(type);
		subelement = ClassTemplateHelper.firstCharToLowerCase(subelement);

		String intendation = "";
		if (handleExeption)
			intendation = "	";
		return tryStart(" 			", handleExeption) + NEW_LINE + intendation + "			" + type + "." + "set"
				+ ClassTemplateHelper.firstCharToUpperCase(subelement + _dataClassPostfix) + "Array(read"
				+ ClassTemplateHelper.firstCharToUpperCase(subelement) + _dataClassPostfix + "());" + NEW_LINE
				+ tryEnd(" 			", handleExeption, subelement);
	}

	public String getReadSubArReaderMethod(String subelement) {
		String originalSubelement = subelement;
		subelement = ClassTemplateHelper.firstCharToLowerCase(subelement);

		String cname = ClassTemplateHelper.firstCharToUpperCase(subelement + _dataClassPostfix + _packerClassPostfix);
		return "		private function read" + ClassTemplateHelper.firstCharToUpperCase(subelement) + _dataClassPostfix
				+ "() : Array" + NEW_LINE + "		{" + NEW_LINE + "			var rAr:Array = [];" + NEW_LINE
				+ "			for each(var xml:XML in _xml['" + originalSubelement + "'])" + NEW_LINE + "			{" + NEW_LINE
				+ "				var reader:" + cname + " = new " + cname + "(xml);" + NEW_LINE + " 				rAr.push(reader.read());"
				+ NEW_LINE + "			}" + NEW_LINE + "			return rAr;" + NEW_LINE + "		}" + NEW_LINE;
	}

	private String tryStart(String intendation, boolean handleExeption) {
		if (!handleExeption)
			return "";
		return intendation + "try" + NEW_LINE + intendation + "{";
	}

	private String tryEnd(String intendation, boolean handleExeption, String errorname) {
		if (!handleExeption)
			return "";
		return intendation + "} catch(" + errorname + "Error:Error) {}" + NEW_LINE;
	}
}